General Coding Style guide for PHP scripting ============================================ Created February 09th 2004. Updated August 22th 2006. Although this coding style guide differs from the well known '[PHP Coding Standard][INTRO1]', we STRONGLY advise you to take a peak at the original in the first place (yes, we did steal bits from it), and also at the [PEAR's coding standards][INTRO2]. Note : the present document is formatted using [Markdown syntax][INTRO3] [INTRO1]: http://www.dagbladet.no/development/phpcodingstandard/ "PHP coding Standard" [INTRO2]: http://pear.php.net/manual/en/standards.php "PEAR Coding Standards" [INTRO3]: http://daringfireball.net/projects/markdown/ "Markdown" -------- * Naming Rules : + Variable and function names + Constant names + Library files + Configuration files * General Rules : + PHP file extensions + End of Line + Line length + Comments + Indent style & Curly brace policy + Switch + Inline documentation + PHP Code tags * Details : + Parens policy + String concatenation + Operators * Recommendations : + Boolean expression + Don't forget the built-in array functions + Embedded Assignments + $_POST and $_GET arrays + Gotcha Keywords + if (FALSE) { } -------- ### Naming Rules : First of all, english is the only language that may be used within source files. #### Variable and function names Variable and function names must be appropriate : names are the most precious clues to understand source code. Please use abbreviate words with care, one may not have to decypher a name. - For a variable name, you could add a suffixe: Max : to mean the maximum value something can have. Cnt : the current count of a running count variable. Key : key value. - For a function name, please remember those prefixes: is : to ask a question about something : expect a Boolean can : to ask a question about something : expect a Boolean get : get a value set : set a value. example: $query = "SELECT count(msg_id) FROM messages WHERE ...."; $answer= @mysql_query($query, $handle); if (! $answer) { $msgCnt= 0; } else { @mysql_result($answer,0,0); } function isMsgAuthor() function getLevel() function canDeleteMsg() Always use the name 'result' for the value to be returned by a function. First character in a name is lower case; Use upper case letters as word separators, lower case for the rest of a word. No underbars ('_') ex: getMailHeader() Function names MUST ALWAYS begin with the 'SK_' prefixe. ex: SK_getMailHeader() #### Constant names Constants must be all caps with '_' separators. #### Library files Library file names must always begin with 'SKlib_', rest of the name should be lower case. Your are advised to choose a one word name. ex: SKlib_string.php, SKlib_archive.php The file which defines constant should begin with 'SKcst_' and share the same name. ex: SKcst_archive.php #### Configuration files Configuration file (other files) names should be simple and meaningful, and all lower case. ex: sitemap.php -------- ### General Rules : #### PHP file extensions Always use the extension '.php' for PHP files (.inc, .php3, .phtml or whatever are NOT allowed). #### End of Line Always use UNIX file format ('LF' must be the end of line character). #### Line length Line length may not exceed 80 colons. #### Comments Comments are found before the line or code block explained. example : // common keys $commun= array_intersect(array_keys($template), array_keys($array)); You should use Unix shell-style comments for configuration or constant declarations, and 'C', 'C++' style comments for 'actual' source code. You must not mix shell and C/C++ comments inside one file (constant declarations and function definitions are in separate files). please use the following C style comment layout /* * first line * second */ In order to improve code readability, you are advised to use comments as horizontal rulers : /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Each file should have its own header, summing up its inner working, and displaying an accurate function's protoypes list (in the same order than functions are found through the file). #### Indent style & Curly brace policy Use TWO spaces for each level of indentation. Tabs' width must be set to HEIGHT chars. You are allowed to substitute tabs for spaces. Comments' indentation should be one space less than code. Brace policy somehow derivates from good ol' "BSD/Allman style"; please don't use "K&R", nor "GNU", nor devilish "whitesmith". If none of the previous style did ring a bell, check the [wikipedia page][INDENT1]. You're allowed to write code on the same line than the opening brace. You are strongly encouraged to always use curly braces even in situations where they are technically optional. example: if (SK_ENCRYPT != $mode) { for ($i=$datalen ; $i-->8 ; ) { $result[$i]= chr( ord($result[$i]) ^ ord($result[$i-1]) ); } } else { $length= $datalen+8; for ($i=1 : $i<$length ; $i++) { $result[$i]= chr( ord($result[$i]) ^ ord($result[$i-1]) ); } } You could also add a comment after the closing brace, repeating the control statement. example: if (! $handle) { /* pass - wrong mysql link identifier */ } elseif (! is_string($pattern)) { $result= @mysql_list_dbs($handle); } else { $pattern= @__SK_mysql_escapeString($handle, $pattern); if (empty($pattern)) { $result= @mysql_list_dbs($handle); } else { $buffer= 'SHOW DATABASES LIKE \''. $pattern .'\''; $result= @mysql_query($buffer, $handle); } // if (empty($pattern)) else } // if (! is_string($pattern)) else [INDENT1]: http://en.wikipedia.org/wiki/Indent_style "Indent style on wikipedia" #### Switch You are allowed to use the 'switch' statement (that one is for epita students). If there are more than one statement, then put a line break after ':' and add an indentation level. You are advised to use blank lines as case separator. example: switch (getUserInfosClear($login, $passw, $struct)) { case 0 : // $struct[3] stands for the level, $struct[2] gives the uid value if ( !isValidLevel($struct[3]) ) { return (ERR_UNKNOW_LEVEL); } else if ( !isValidUsrId($struct[2]) ) { return (ERR_UNKNOW_ACCOUNT); } else if ( isCPNOLOGIN($struct[3]) ) { return (ERR_CPNOLOGIN); } // seems like something is missing... break; case 3 : return (ERR_UNKNOW_ACCOUNT); case 4 : return (ERR_WRONG_PASSW); case 5 : return (ERR_ACCES_DENIED); default : return (ERR_INCOMPLETE_FORM); } // switch (getUserInfos(...)) #### Inline documentation A documentation comment MUST ALWAYS precede each (non-hidden) function. The documentation format derivates from the well known [Javadoc convention][CODEDOC1]. - The first line only contains the begin-comment delimiter (/**). - The function prototype must follow, then a blank line as separator - The first sentence (do not forget the period '.') as a short summary. - Insert a blank comment line between the description and the list of tags. - The last line contains the end-comment delimiter (*/) Note that unlike the begin-comment delimiter, the end-comment contains only a single asterisk. You can use the following tags; See [javadoc documentation][CODEDOC2] for further informations. @author @param @return @see @since @version You are advised to use the custom tag '@require' (see example). example: /** * int SK_mysql_serverVersion(resource handle) * * Returns the version of the MySQL server as an integer. * 'SK_mysql_serverVersion()' simulates the 'mysqli_get_server_version()' * function introduced with PHP5; it returns the version of the server * connected to (represented by the link parameter) as an integer. * * The form of this version number is * main_version * 10000 + minor_version * 100 + sub_version * (i.e. : version 4.0.1-alpha is 40010). * * If the supplied link identifier is found to be invalid, * then 0 is returned. * * @require PHP 4.0.5 * * @param handle MySQL link identifier * @return integer value representing the server * version, 0 if link is invalid */ [CODEDOC1]: http://en.wikipedia.org/wiki/Javadoc "Javadoc on wikipedia" [CODEDOC2]: http://java.sun.com/j2se/javadoc/writingdoccomments/ "How to Write Doc Comments for the Javadoc Tool" #### PHP Code tags Always use "" to delimit PHP code, NOT the "" shorthand. You'd better use "" instead of "". There is a line break after "". The opening PHP tag MUST be at the very beginning of the line. example: -------- ### Details : #### Parens policy Do not put parens next to keywords, put a space between; but DO put parens next to function names. Always use parens in return statements ('return' is a keyword) Inside a 'for' statement a space is needed on both sides of each semicolon. example: // reduce numArg to an even value $numArg= ($numarg >> 1) << 1; for ($i=1 ; $i<$numArg ; $i+=2) { $result.= func_get_arg($i) .'='. func_get_arg($i+1) .'&'; } // (...) return ($result); #### String concatenation Do put a space char between the dot '.' operator and variable or function calls. Don't put space between the dot operator and a quoted string. example: if (isset( $parsed['query'] )) { $result.= '?'. $parsed['query'] .'&'. $sessId; } else { $result.= '?'. $sessId; } if (isset( $parsed['fragment'] )) { $result.= '#'. $parsed['fragment']; } return ($result); #### Operators Don't put space for unary operators, and 'cast'. example: $m= -$n; -------- ### Recommendations : #### Boolean expression Most of the time, do not default the test for non-zero, i.e. if (FAIL != callFunction()) is better than if (callFunction()) Do not check a boolean value for equality with 1 (TRUE, YES, etc.); instead test for inequality with 0 (FALSE, NO, etc.) if (FALSE != func()) /* good */ if (TRUE == func()) /* wrong */ #### Don't forget the built-in array functions Don't forget to check the PHP documentation when you need a specific array function. A lot of them are already available. http://www.php.net/manual/en/ref.array.php http://www.php.net/manual/en/control-structures.foreach.php #### Embedded Assignments Avoid embedded assignments, especially inside control statements. $d= ($a= $b + $c) + $r; /* wrong */ #### $_POST and $_GET arrays Forget about $HTTP_*_VARS, use $_POST and $_GET instead. #### Gotcha Keywords You are strongly encouraged to use 'Gotcha keywords'. Some keywords: - :TODO: topic means there's more to do here, don't forget. - :BUG: [bugid] topic means there's a Known bug here, explain it and optionally give a bug ID. - :INFO: topic Additional informations about a non-PHP topic; Should be used for 'complex' SQL queries - :TRICKY: topic tells somebody that the following code is very tricky so don't go changing it without thinking. - :WARNING: topic beware of something. Usually WARNING is 'stronger' than TRICKY - :KLUDGE: topic when you've done something ugly say so and explain how you would do it differently next time if you had more time. example : /* :WARNING: KEY_STRENGHT * * the implementation supports dynamic key resizing which prevents * statistic attacks _even in ECB mode_. it will build a minimal key * of 256 bits with no apparent pattern matching. this mode _cannot_ * be used in some countries that's why it is disabled by default. * To enable dynamic key resizing, turn KEY_STRENGHT to a value of 0. */ /* :INFO: MySQL 'DATABASE()' function * * DATABASE() Returns the current database name, if there is no * current database, DATABASE() returns the empty string. */ #### if (FALSE) { } Sometimes large blocks of code need to be commented out for testing. The easiest way to do this is with an 'if (0)' or 'if (FALSE)' block: function example() { great looking code if (0) { ignore } more code } You can't use C style comments /* */ because those can't be nested 'C', and surely a large block of your code will contain a comment, won't it ? It is even easier if your text editor can comment out/uncomment selected text block.